from flask import Flask, request, jsonify
from flask_cors import CORS
from tools.myjwt import JWTManager
from tools.myredis import redis_manager
from tools.db import init_db

app = Flask(__name__)
CORS(app, origins=['http://localhost:5173', 'http://127.0.0.1:5173', 'http://localhost:3000', 'http://127.0.0.1:3000'], supports_credentials=True, methods=['GET','POST','PUT','DELETE','OPTIONS'], allow_headers=['Content-Type','Authorization','X-Requested-With'])

# 初始化数据库
db = init_db(app, use_mysql=True)

# 注册蓝图
from views.user import user_blue
from views.menu_api import menu_bp
from views.business_api import business_bp
app.register_blueprint(user_blue, url_prefix='/api/user')
app.register_blueprint(menu_bp, url_prefix='/api')
app.register_blueprint(business_bp, url_prefix='/api')

# 白名单URLs - 不需要token验证的路径
WHITELIST_URLS = [
    '/api/user/login',
    '/api/health',
    '/api/status',
    '/api/menus',
    '/api/products',
    '/api/customers'
]

# 权限配置
PERMISSION_CONFIG = {
    'admin': {
        'paths': ['/api/admin/*', '/api/orders/*', '/api/user/*'],
        'methods': ['GET', 'POST', 'PUT', 'DELETE']
    },
    'user': {
        'paths': ['/api/user/userinfo', '/api/orders/*'],
        'methods': ['GET', 'POST']
    }
}

def is_whitelisted(path):
    """检查路径是否在白名单中"""
    return any(path.startswith(url.rstrip('*')) for url in WHITELIST_URLS)

def has_permission(user_id, path, method):
    """检查用户权限"""
    user_role = 'admin' if user_id == 1 else 'user'  # 简化角色判断
    user_permissions = get_user_permissions(user_id)
    
    allowed_paths = user_permissions.get('paths', [])
    allowed_methods = user_permissions.get('methods', [])
    
    # 检查路径权限
    path_allowed = any(path.startswith(p.rstrip('*')) for p in allowed_paths)
    method_allowed = method in allowed_methods
    
    return path_allowed and method_allowed

def get_user_permissions(user_id):
    """获取用户权限配置"""
    user_role = 'admin' if user_id == 1 else 'user'  # 简化角色判断
    return PERMISSION_CONFIG.get(user_role, {})

@app.before_request
def before_request():
    # 处理OPTIONS预检请求，直接放行
    if request.method == 'OPTIONS':
        return '', 200
    """
    请求前中间件 - 完整的token验证流程
    
    验证步骤：
    1. 检查是否在白名单中
    2. 检查是否携带token
    3. 检查token格式是否正确
    4. 检查token是否被修改
    5. 检查token是否过期
    6. 检查token是否已退出（黑名单）
    7. 检查用户权限
    """
    current_path = request.path
    current_url = request.url
    request_method = request.method
    
    print(f"[AUTH] 请求路径: {current_path}")
    print(f"[AUTH] 请求方法: {request_method}")
    print(f"[AUTH] 完整URL: {current_url}")
    
    if is_whitelisted(current_path):
        print(f"[AUTH] 路径 {current_path} 在白名单中，跳过验证")
        return None
    
    print(f"[AUTH] 路径 {current_path} 不在白名单中，开始token验证")
    
    auth_header = request.headers.get('Authorization')
    if not auth_header:
        print("[AUTH] 错误: 缺少Authorization头")
        return jsonify({
            "code": 401,
            "message": "缺少认证令牌，请先登录",
            "error_type": "missing_token"
        }), 401
    
    print(f"[AUTH] 找到Authorization头: {auth_header[:20]}...")
    
    try:
        if not auth_header.startswith('Bearer '):
            print("[AUTH] 错误: token格式不正确，应该以'Bearer '开头")
            return jsonify({
                "code": 401,
                "message": "令牌格式错误，应该以'Bearer '开头",
                "error_type": "invalid_format"
            }), 401
        
        token = auth_header.split(' ')[1]
        if not token:
            print("[AUTH] 错误: token为空")
            return jsonify({
                "code": 401,
                "message": "令牌不能为空",
                "error_type": "empty_token"
            }), 401
            
    except IndexError:
        print("[AUTH] 错误: token解析失败")
        return jsonify({
            "code": 401,
            "message": "令牌格式错误，无法解析",
            "error_type": "parse_error"
        }), 401
    
    print(f"[AUTH] 提取到token: {token[:20]}...")
    
    if redis_manager.is_token_blacklisted(token):
        print("[AUTH] 错误: token在黑名单中（用户已退出登录）")
        return jsonify({
            "code": 401,
            "message": "令牌已失效，用户已退出登录，请重新登录",
            "error_type": "token_blacklisted"
        }), 401
    
    print("[AUTH] token不在黑名单中")
    
    payload = JWTManager.decode_token(token)
    if 'error' in payload:
        error_msg = payload['error']
        print(f"[AUTH] 错误: token验证失败 - {error_msg}")
        
        if 'expired' in error_msg.lower() or 'exp' in error_msg.lower():
            return jsonify({
                "code": 401,
                "message": "令牌已过期，请刷新令牌或重新登录",
                "error_type": "token_expired"
            }), 401
        elif 'invalid' in error_msg.lower():
            return jsonify({
                "code": 401,
                "message": "令牌无效或已被修改，请重新登录",
                "error_type": "token_invalid"
            }), 401
        else:
            return jsonify({
                "code": 401,
                "message": f"令牌验证失败: {error_msg}",
                "error_type": "token_verification_failed"
            }), 401
    
    print("[AUTH] token验证成功")
    
    token_type = payload.get('token_type')
    if token_type != 'access':
        print(f"[AUTH] 错误: 错误的token类型 - {token_type}")
        return jsonify({
            "code": 401,
            "message": "令牌类型错误，请使用访问令牌",
            "error_type": "wrong_token_type"
        }), 401
    
    print(f"[AUTH] token类型正确: {token_type}")
    
    user_id = payload.get('user_id')
    username = payload.get('username')
    
    if not user_id or not username:
        print("[AUTH] 错误: token中缺少用户信息")
        return jsonify({
            "code": 401,
            "message": "令牌中缺少用户信息",
            "error_type": "missing_user_info"
        }), 401
    
    print(f"[AUTH] 用户信息: ID={user_id}, 用户名={username}")
    
    if not has_permission(user_id, current_path, request_method):
        print(f"[AUTH] 错误: 用户 {username} 没有权限访问 {current_path}")
        return jsonify({
            "code": 403,
            "message": "权限不足，无法访问该资源",
            "error_type": "insufficient_permission"
        }), 403
    
    print(f"[AUTH] 权限检查通过")
    
    request.current_user = payload
    print(f"[AUTH] 用户 {username} 验证成功，允许访问")
    
    return None

# 测试接口
@app.route('/api/health', methods=['GET'])
def health():
    """健康检查接口"""
    return jsonify({
        "code": 200,
        "message": "服务正常",
        "data": {
            "status": "healthy",
            "timestamp": "2024-01-01T00:00:00Z"
        }
    }), 200

@app.route('/api/status', methods=['GET'])
def status():
    """状态检查接口"""
    return jsonify({
        "code": 200,
        "message": "系统状态正常",
        "data": {
            "redis_connected": redis_manager.redis_client is not None,
            "timestamp": "2024-01-01T00:00:00Z"
        }
    }), 200

@app.route('/api/admin/users', methods=['GET'])
def admin_users():
    """管理员用户列表接口"""
    return jsonify({
        "code": 200,
        "message": "获取用户列表成功",
        "data": {
            "users": [
                {"id": 1, "username": "admin", "role": "admin"},
                {"id": 2, "username": "user1", "role": "user"}
            ]
        }
    }), 200

@app.route('/api/orders', methods=['GET'])
def orders():
    """订单列表接口"""
    return jsonify({
        "code": 200,
        "message": "获取订单列表成功",
        "data": {
            "orders": [
                {"id": 1, "title": "订单1", "status": "已完成"},
                {"id": 2, "title": "订单2", "status": "进行中"}
            ]
        }
    }), 200

if __name__ == '__main__':
    print("🚀 启动Flask应用")
    print("📝 功能特性:")
    print("   ✅ JWT认证")
    print("   ✅ Redis黑名单")
    print("   ✅ Token刷新")
    print("   ✅ 权限控制")
    print("   ✅ 白名单机制")
    print("🔗 访问地址: http://localhost:5000")
    print("📊 健康检查: http://localhost:5000/api/health")
    print("📈 状态检查: http://localhost:5000/api/status")
    app.run(debug=True, host='0.0.0.0', port=5000)
